//===============================================================================
// Microsoft patterns & practices Enterprise Library Contribution
// Query Application Block
//===============================================================================

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using EntLibContrib.Query.Configuration.Design;
using EntLibContrib.Query.Configuration.Design.ViewModel;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ContainerModel;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Design;

namespace EntLibContrib.Query.Configuration
{
	/// <summary>
	/// Overall configuration settings for Queries
	/// </summary>    
    [ViewModel(typeof(QuerySettingsViewModel))]
    [ResourceDescription(typeof(DesignResources), "QuerySettingsDescription")]
    [ResourceDisplayName(typeof(DesignResources), "QuerySettingsDisplayName")]
    public class QuerySettings : SerializableConfigurationSection, ITypeRegistrationsProvider
	{
		/// <summary>
		/// Configuration key for query settings.
		/// </summary>
		public const string SectionName = "queryConfiguration";
		private const string commandsProperty = "commands";
		private const string parameterSetsProperty = "parameterSets";
		private const string queriesProperty = "queries";

	    /// <summary>
        /// Gets the collection of defined <see cref="IQuery"/> objects.
        /// </summary>
        /// <value>
        /// The collection of defined <see cref="IQuery"/> objects.
        /// </value>
        [ConfigurationProperty(queriesProperty, IsRequired = false)]
        [ConfigurationCollection(typeof(QueryDataBase))]
        [ResourceDescription(typeof(DesignResources), "QueriesDescription")]
        [ResourceDisplayName(typeof(DesignResources), "QueriesDisplayName")]
        public NameTypeConfigurationElementCollection<QueryDataBase, CustomQueryData> Queries
        {
            get { return (NameTypeConfigurationElementCollection<QueryDataBase, CustomQueryData>)base[queriesProperty]; }
        }

		/// <summary>
		/// Gets the collection of defined <see cref="IParameterSet"/> objects.
		/// </summary>
		/// <value>
		/// The collection of defined <see cref="IParameterSet"/> objects.
		/// </value>
		[ConfigurationProperty(parameterSetsProperty, IsRequired = false)]
        [ConfigurationCollection(typeof(ParameterSetData))]
        [ResourceDescription(typeof(DesignResources), "ParameterSetsDescription")]
        [ResourceDisplayName(typeof(DesignResources), "ParameterSetsDisplayName")]
        [Command(QueryDesignTime.CommandTypeNames.AddParameterSetCommand, CommandPlacement = CommandPlacement.ContextAdd, Replace = CommandReplacement.DefaultAddCommandReplacement)]
        public NamedElementCollection<ParameterSetData> ParameterSets
		{
            get { return (NamedElementCollection<ParameterSetData>)base[parameterSetsProperty]; }
		}

        /// <summary>
        /// Gets the collection of <see cref="CommandData"/> objects for commands.
        /// </summary>
        /// <value>
        /// The collection of <see cref="CommandData"/> objects.
        /// </value>
        [ConfigurationProperty(commandsProperty, IsRequired = false)]
        [ConfigurationCollection(typeof(CommandData))]
        [ResourceDescription(typeof(DesignResources), "CommandsDescription")]
        [ResourceDisplayName(typeof(DesignResources), "CommandsDisplayName")]
        public NameTypeConfigurationElementCollection<CommandData, CustomCommandData> Commands
        {
            get { return (NameTypeConfigurationElementCollection<CommandData, CustomCommandData>)base[commandsProperty]; }
        }

		/// <summary>
		/// Creates the <see cref="TypeRegistration"/> entries to use when configuring a container for the Query Block.
		/// </summary>
		/// <returns></returns>
		public IEnumerable<TypeRegistration> GetRegistrations(IConfigurationSource configurationSource)
		{
			var registrations = new List<TypeRegistration>();

            registrations.AddRange(Queries.SelectMany(x => x.GetRegistrations()));
            registrations.AddRange(ParameterSets.SelectMany(x => x.GetRegistrations()));
            registrations.AddRange(Commands.Select(x => x.GetRegistration()));

			return registrations;
		}
		
		/// <summary>
		/// Return the <see cref="TypeRegistration"/> objects needed to reconfigure
		/// the container after a configuration source has changed.
		/// </summary>
		/// <remarks>If there are no reregistrations, return an empty sequence.</remarks>
		/// <param name="configurationSource">The <see cref="IConfigurationSource"/> containing
		/// the configuration information.</param>
		/// <returns>The sequence of <see cref="TypeRegistration"/> objects.</returns>
		public IEnumerable<TypeRegistration> GetUpdatedRegistrations(IConfigurationSource configurationSource)
		{
			return GetRegistrations(configurationSource);
		}
	}
}